home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr48 / file211.zip / FILEDEF.DOC < prev    next >
Text File  |  1993-04-07  |  12KB  |  232 lines

  1.  
  2. File Formats for Searchlight BBS    (as of ver 2.11)
  3. --------------------------------
  4.  
  5. Introduction
  6. ------------
  7. This ZIPfile contains the data types for Searchlight BBS data files as of 
  8. version 2.11, released on 3/4/91.  These data types should be considered 
  9. stable.
  10.  
  11. No executable code is being provided with this release of the data types.  
  12. This is primarily because the code necessary to access the data in 
  13. Searchlight 2.0 is complex, and a user oriented library needs to be 
  14. developed.  I would not encourage authors to attempt to write code to access 
  15. Searchlight 2.0 subboards at this point: wait for a filedef release which 
  16. includes the code library.  Access to the CONFIG file is much the same as in 
  17. version 1.x and should not be a problem at this point.
  18.  
  19. The data contained in these documents is only the tip of the iceberg.  Below 
  20. is an overview of the general structure of Searchlight 2.0 data files which 
  21. outlines the similarities between them.  Discussions of the individual data 
  22. files will be provided in future editions.  As well, I plan to release some 
  23. code libraries, either as source or as Turbo Pascal units, for accessing 
  24. SLBBS files.  Those who program in Pascal may want to wait for the release 
  25. of these tools before desigining major applications.
  26.  
  27.  
  28. Searchlight 2.0 File Overview
  29. -----------------------------
  30. The Searchlight CONFIG, CHAT and NODES files operate much the same way as in 
  31. version 1.x, except for the addition and reorganization of the data fields.  
  32. NODES.SL2 is the same file as SYSTEM.BBS in previous versions.
  33.  
  34. There is a major difference between the way Searchlight 2.0 handles its 
  35. other data files as compared to all previous versions of SLBBS.  If you plan 
  36. to do any work with SLBBS beyond reading the CONFIG file, it is vitally 
  37. important that you read, and understand, the following discussion.  
  38.  
  39. Previous versions of Searchlight used a standard "File Of Type" approach to 
  40. all of its data files.  That is, each data file was declared in the Pascal 
  41. source code as a file of some record type; for example:
  42.  
  43.   Var userfile: file of usertype;
  44.  
  45. Physically, the disk image of each Searchlight 1.x file consists of any 
  46. number of uniform records, each the same size and type.
  47.  
  48. This is emphatically NOT the case with Searchlight 2.0.  All SLBBS data 
  49. files, with the exception of the CONFIG, CHAT and NODES files, are declared 
  50. as "file of byte" within the Searchlight source code.  In actuality, each 
  51. data file is, for the most part, composed of fixed size records, but there 
  52. are various data fields placed at the beginning of each file which do not 
  53. conform to the size or type of the records that make up the bulk of the 
  54. file.
  55.  
  56. Before I continue, a word about why this file format was developed may be 
  57. helpful.  In the course of designing Searchlight 1.x, I noticed that 
  58. different files, such as the USER, MESSAGE and DIR files, had two things in 
  59. common.  The first is that each file consists of records, and requires that 
  60. records be allocated, deleted, and reused.  The second common feature of 
  61. these files is that while they consist of fixed size records, certain 
  62. variable information is associated with each file-- such as the number of 
  63. users in the user file.  In Searchlight 1.x, essentially the same code to 
  64. allocate and delete records from these data files had to be rewritten 
  65. specifically for each file.  The various "extra" pieces of information for 
  66. each file were tucked in unused fields wherever these could be found.
  67.  
  68. The first part of writing Searchlight 2.0 was to design a universal file 
  69. management scheme that could handle the basic file maintenance chores of any 
  70. data file, thus greatly reducing the amount of effort I would need to create 
  71. new files.  The result is a general file library that underlies all of 
  72. Searchlight's block-oriented files; I call this the Block File manager.
  73.  
  74. Searchlight's block file manager divides each file into three parts:
  75.  
  76.   (1) A Standard Header part. This is a fixed size record (defined as
  77.       FileHeader in BLOCK.PAS) which contains the sizes in bytes of the
  78.       variable header and data records, as well as a pointer to the next
  79.       free data record.
  80.  
  81.   (2) A Variable Header part.  This is any number of bytes containing any
  82.       general "header" information required by the file.
  83.  
  84.   (3) Data blocks.  Any number of data records associated with the file;
  85.       the size of each record is defined in the standard header.
  86.  
  87. Searchlight 2.0 also uses standard procedures to maintain its binary tree 
  88. indexes (user, setup, member and DIR files).  The index information is 
  89. defined in BLOCK.PAS.
  90.  
  91.  
  92. The User File: An Example
  93. -------------------------
  94. The Searchlight user file is divided into three parts, as per the block file 
  95. manager.  First is the standard header (FileHeader); followed by the user 
  96. file header (UserHeader); then the individual user records (UserType).  The 
  97. first data record of all Searchlight files is always referred to as record 1.
  98.  
  99. Here is the general procedure you'd use to access the user file:
  100.  
  101. (1) Open the file as a FILE OF BYTE.  Example:
  102.  
  103.     var userfile: file of byte;
  104.      ...
  105.     assign(userfile,'USER.SL2');
  106.     reset(userfile,1);
  107.  
  108. (2) Read the FileHeader, which is always the first information in the file:
  109.  
  110.     var header: fileheader;
  111.      ...
  112.     seek(userfile,0);
  113.     blockread(userfile,header,sizeof(header));
  114.  
  115. (3) The "Header" record now tells you the size of each user record, as well
  116.     as the offset in the file to record 1.  The data between the start of 
  117.     record 1 and the end of the standard header is the UserHeader data.
  118.  
  119.     Here is an example of how to read the UserHeader:
  120.  
  121.     var h: userheader;
  122.      ...
  123.     seek(userfile,sizeof(fileheader));
  124.     blockread(userfile,h,sizeof(h));
  125.  
  126. (4) Here is an example of how to read any arbitrary record from the user
  127.     file, assuming "N" is the record number you want to read (N should be of 
  128.     type longint):
  129.  
  130.     var user: usertype;
  131.      ...
  132.     seek(userfile,(sizeof(user)*(n-1))+sizeof(fileheader)+sizeof(userheader));
  133.     blockread(userfile,user,sizeof(user));
  134.  
  135.  
  136. These examples use the SIZEOF function to obtain the sizes of the data 
  137. records being retrieved; however, you can also get this information from the 
  138. FileHeader data at the top of the file.  FileHeader.RecSize contains the 
  139. size of the data blocks in the file (in this case, the same as sizeof(user))
  140. and FileHeader.Offset contains the offset to the first block of data past 
  141. the header information (in this case, equal to sizeof(fileheader)+sizeof
  142. (userheader)).  Thus, assuming the variable "header" contains the fileheader
  143. information read in step (2) above, step (4) could be rewritten as:
  144.  
  145.     seek(userfile,(header.recsize*(n-1))+header.offset);
  146.     blockread(userfile,user,header.recsize);
  147.  
  148. Why is this important?  Because it applies to ALL Searchlight data files 
  149. including the subboard header, text and member files; the DIR files; the 
  150. Setup files (SUBBOARD.SL2, FILEDIR.SL2); and even the Quotes file.  The 
  151. block definition provides a universal way to access data in any of these 
  152. files, so that the same procedures can operate on all of them without 
  153. knowing the data types involved.  
  154.  
  155.  
  156. The RecordHeader Type
  157. ---------------------
  158. RecordHeader (defined in BLOCK.PAS) is a data type which is superimposed 
  159. (typecast) onto the data records in Searchlight files for the purpose of 
  160. maintaining a list of free records.  Although the type definition Record-
  161. Header doesn't appear as part of the data records in FILEDIR.DEF, the block 
  162. file manager writes records of this type on top of the actual data in the 
  163. file records when it deletes a record from the file.  Since the record is 
  164. being deleted, it doesn't really matter that its data is overwritten.  
  165. RecordHeader contains the following fields:
  166.  
  167.      RecordHeader = record    { control header to records }
  168.        mark: byte;                 { FF to indicate deleted rec }
  169.        extra: byte;
  170.        next: longint;              { ptr to next free rec }
  171.      end;
  172.  
  173. MARK is set to a value of 255 ($FF) to indicate that the record is deleted.  
  174. This helps programs that process files sequentially identify and skip 
  175. deleted records.  The data files in Searchlight always reserve the first 
  176. byte of each record in order to accomodate the $FF mark without the 
  177. possibility of overwriting it.  The subboard message (MSG) files use the 
  178. mark byte as a counter to indicate the number of copies of a record that are 
  179. currently in use (additional copies of a text record are created when 
  180. mail is sent to more than one recipient).
  181.  
  182. The NEXT pointer points to the next free record on the list: and the first 
  183. free record on the list is pointed to by the "NextFree" pointer in the 
  184. FileHeader.  The way to ALLOCATE a record in any Searchlight file is to take 
  185. the first free record pointed to by NextFree off of the linked list by 
  186. pointing NextFree to the NEXT value in the first free record.  If there are 
  187. no free records (NextFree=0) then the file must be physically expanded.  The 
  188. way to DELETE any record in a Searchlight file is to add it to the free 
  189. record list (inserting it at the top of the list is most efficient).
  190.  
  191.  
  192. The TreeRoot and TreeLeaf types
  193. -------------------------------
  194. These data types, declared in BLOCK.PAS, define the binary tree structure 
  195. used by Searchlight's user, member, Setup and DIR files.  Additionally, the 
  196. linked list type (used by the Files program to store files by date) is 
  197. defined as part of these structures.  
  198.  
  199.      TreeRootType = record     { root info for tree/list type files }
  200.        treeroot: longint;      { root of tree }
  201.        listroot: longint;      { linked list root }
  202.        entries: longint;       { # of entries }
  203.      end;
  204.  
  205.      TreeLeafType = record     { leaf info for tree/list type files }
  206.        status: byte;           { 0=active, 255=deleted }
  207.        left,right: longint;    { pointers to child nodes }
  208.        last,next: longint;     { linked list ptrs }
  209.      end;
  210.  
  211. Files which use the binary tree index have a TreeRootType declared as the 
  212. FIRST element in their file headers (the first data after the standard 
  213. FileHeader information) and have a TreeLeafType declared as the FIRST 
  214. element of each data record.  Notice that the first byte of TreeLeafType is 
  215. a byte called status; since TreeLeafType is the first data in each record, 
  216. the first byte of it overlays the first byte of RecordHeader.  Therefore, 
  217. the value TreeLeafType.status can be compared to 255 ($FF) to determine 
  218. whether a record is active or deleted.
  219.  
  220. To traverse the binary tree, start with the TreeRootType.treeroot value 
  221. (which indicates the record number of the first entry).  Then follow the 
  222. TreeLeafType.left and TreeLeafType.right pointers to the records. Remember 
  223. that each of these pointers is a longint value which represents the record 
  224. number of the pointed to data.  In order to retrieve the record, use a 
  225. formula such as the one shown in part (4) of the user file example above.
  226.  
  227. To follow the date sorted list (in file DIR files), start with listroot and 
  228. follow the TreeLeaf.next pointers forward.  Since the first entry on the 
  229. linked list is the most recent file, "forward" actually means backward in 
  230. time.  TreeLeaf.last can be used to follow the list backward if desired.
  231.  
  232.